package com.jacky.demo.util;

import android.text.InputFilter;
import android.text.InputType;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.NumberKeyListener;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * InputFilter的扩展
 */

public interface InputFilterExtra {

    /**
     * 身份证过滤
     */
    class CardIDFilter extends NumberKeyListener {

        @Override
        protected char[] getAcceptedChars() {
            return new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'x', 'X'};
        }

        @Override
        public int getInputType() {
            return InputType.TYPE_CLASS_TEXT;
        }

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            CharSequence s = super.filter(source, start, end, dest, dstart, dend);
            if("".equals(s)) return "";
            int length = dest.length();
            if(length >= 18) return "";
            if(length < 17) {
                for(int i = start;i < end;i++) {
                    char c = source.charAt(i);
                    if(c == 'x' ||c == 'X') { //只有身份证的最后一位才能是字母X，其他位都是数字
                        return "";
                    }
                }
            }
            return s;
        }
    }

    /**
     * 只允许输入中文
     */
    class ChineseFilter implements InputFilter {

        private int mMin = 0x4e00;
        private int mMax = 0x9fa5;

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            StringBuilder builder = new StringBuilder();
            for(int i = start;i < end;i++) {
                char c = source.charAt(i);
                if(c < mMin) continue;
                if(c > mMax) continue;
                builder.append(c);
            }
            return builder;
        }
    }

    /**
     * 限制长度输入，双字节的长度为2，单字节的长度为1
     */
    class LengthInputFilter implements InputFilter {

        private int mMax;

        public LengthInputFilter(int length) {
            mMax = length;
        }

        @Override
        public CharSequence filter(CharSequence source, int start, int end,
                                   Spanned dest, int dstart, int dend) {

            int keep = mMax;
            for(int i = dest.length() - 1;i >= dend;i-- ) {
                if(isDoubleWord(dest.charAt(i))) keep -= 2;
                else keep--;
            }
            for(int i = dstart - 1;i >= 0;i-- ) {
                if(isDoubleWord(dest.charAt(i))) keep -= 2;
                else keep--;
            }

            if (keep <= 0) {
                return "";
            } else {
                for(int i = start;i < end;i++) {
                    char c = source.charAt(i);
                    if(isDoubleWord(c)) keep -= 2;
                    else keep--;

                    if(keep < 0) return source.subSequence(start, i);
                }
                return source;
            }
        }

        private boolean isDoubleWord(char c) {
            return c > 0xff;
        }
    }

    /**
     * 输入框小数点精度控制
     */
    class DecimalInputFilter extends NumberKeyListener {

        private static final char[] ACCEPT1 =
                { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '.', '%'};
        private static final char[] ACCEPT2 =
                { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '.'};

        private final int mPrefix;
        private final int mSuffix;
        private boolean mPercent;

        /**
         * 数字输入控制
         * @param prefix 小数点前可输入的数字个数
         * @param suffix 小数点后可输入的数字个数
         * @param percent 是否显示百分号
         */
        public DecimalInputFilter(int prefix,int suffix, boolean percent) {
            mPrefix = prefix;
            mSuffix = suffix;
            mPercent = percent;
        }

        /**
         * 数字输入控制
         * @param prefix 小数点前可输入的数字个数
         * @param suffix 小数点后可输入的数字个数
         */
        public DecimalInputFilter(int prefix,int suffix) {
            this(prefix, suffix, false);
        }

        /**
         * 数字输入控制
         * @param suffix 小数点后可输入的数字个数
         */
        public DecimalInputFilter(int suffix) {
            this(Integer.MAX_VALUE, suffix);
        }

        @Override
        public CharSequence filter(CharSequence source, int start, int end,
                                   Spanned dest, int dstart, int dend) {
            CharSequence s = super.filter(source, start, end, dest, dstart, dend);
            if(null != s) { //符合过滤规则的是返回 null，不符合过滤规则的是返回非空
                return s;
            }
            if(TextUtils.isEmpty(source)) {
                return source;
            }

            String dValue = dest.toString();
            int dIndex = dValue.indexOf('.');
            if(".".equals(source)) {
                if(dIndex == -1) return source;
                return ""; //不支持输入多个 “.”
            }

            int diff = 0;
            boolean haspre = dValue.indexOf('%') != -1;

            if(dIndex == -1) { //没有小数点
                diff = dest.length() - mPrefix + 1;
                if(haspre) diff--;
            } else if(dstart <= dIndex) { //输入的信息在小数点前面
                diff = dIndex - mPrefix + 1;
            } else { //输入的信息在小数点后面
                diff = dest.length() - dIndex - mSuffix;
                if(haspre) diff--;
            }

            if (diff > 0) {   //输入的数据超过精度位数，需要过滤
                return source.subSequence(start, end - diff);
            }
            return source;
        }//end filter

        @Override
        public int getInputType() {
            return InputType.TYPE_NUMBER_FLAG_DECIMAL;
        }

        @Override
        protected char[] getAcceptedChars() {
            return mPercent ? ACCEPT1 : ACCEPT2;
        }
    }

    /**
     * Emoji字符过滤
     */
    class EmojiInputFilter implements InputFilter {

        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\ud83e\udc00-\ud83e\udfff]|[\u2600-\u27ff]",
                Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            Matcher emojiMatcher = emoji.matcher(source);
            if (emojiMatcher.find()) {
                return "";
            }
            return null;
        }
    }
}
